
from bcat.iter.iterator import Iterator


class SessionsIterator(Iterator):
    def __init__(self, d):
        self.__d = d 
        self.__iter = iter(d.items())
    def next(self):
        try:
            return self.__iter.__next__()
        except StopIteration:
            return None

class Sessions(object):
    def __init__(self):
        self.__map = {}

    # True -> insert, False -> insert failed
    def insert(self, name, ses):
        if name not in self.__map:
            self.__map[name] = ses
            return True
        else:
            return False

    def delete(self, name):
        if name in self.__map:
            del self.__map[name]
            return True
        else:
            return False

    # replace if name in map or do nothing
    def update(self, name, ses):
        if name in self.__map:
            self.__map[name] = ses
            return True
        else:
            return False

    def contains(self, name):
        return name in self.__map


    # (True, old_v) or (False, None)
    def remove(self, name):
        r = None
        if name in self.__map:
            r = self.__map[name]
            del self.__map[name]
        return (r is not None, r)
            

    
    # if k in =>  update and return old_v
    # if k not-in => insert and return None
    def replace(self, name, ses):
        o = None
        if name in self.__map:
            o = self.__map[name]
        self.__map[name] = ses 
        return o

    def iter(self):
        return SessionsIterator(self.__map)

    def __str__(self):
        s = [] 
        for k, v in self.__map.items():
            s.append(f"{k}:[{v}], ")
        return ''.join(s)


import unittest


class TestSessions(unittest.TestCase):
    class Session(object):
        def __init__(self, name):
            self.__name = name

        @property
        def name(self):
            return self.__name

        def __str__(self):
            return "Session:[{}]".format(self.__name)

    def test_main(self):

        ss = Sessions()
        
        #insert
        name1 = "Trader1"
        ss.insert(name1, TestSessions.Session(name1))
        self.assertTrue(ss.contains(name1))

        self.assertEqual(1, ss.iter().count())

        #delete
        ss.delete(name1)
        self.assertFalse(ss.contains(name1))
        
        #insert
        name = "trader"
        self.assertFalse(ss.contains(name))
        self.assertTrue(ss.insert(name, TestSessions.Session(name)))
        self.assertTrue(ss.contains(name))

        #update
        self.assertTrue(ss.update(name, TestSessions.Session(name1)))
        self.assertTrue(ss.contains(name))

        #remove
        (ok, old) = ss.remove(name)
        self.assertTrue(ok)
        self.assertEqual(name1, old.name)

        #replace => [insert or update]
        self.assertFalse(ss.contains(name))
        self.assertIsNone(ss.replace(name, TestSessions.Session(name))) #insert

        self.assertTrue(ss.contains(name))
        self.assertIsNotNone(ss.replace(name, TestSessions.Session(name1))) #replace
    #end def test_main
    

if __name__ == '__main__':
    unittest.main() 
